package com.qfedu.entity.chapter2.course10;

import java.util.concurrent.TimeUnit;

public class LeakyBucket {
    //上次漏斗漏水的时间
    public long lastLeakyTimeStamp = System.currentTimeMillis(); // 当前时间
    public int burst; // 桶的容量
    // 水漏出的速度,每毫秒处理的数量
    public double rate;
    public int currentWater; // 当前水量(当前累积请求数)

    public LeakyBucket(int burst, double rate) {
        this.burst = burst;
        this.rate = rate;
    }

    /**
     * 漏水
     */
    public void leaky() {
        long now = System.currentTimeMillis();
        //这个是间隔的时间
        long deltaTs = (now - this.lastLeakyTimeStamp);
        //漏掉的水
        int deltaQuota = (int) (deltaTs * rate);
        //桶内剩余的水
        int leftWater = currentWater - deltaQuota;
        // 先执行漏水，计算剩余水量
        currentWater = Math.max(0, leftWater);
        //更新上一次漏水时间为当前时间
        lastLeakyTimeStamp = now;
    }

    /**
     * 加水(新请求）
     *
     * @return
     */
    public boolean acquire(int size) {
        leaky();
        if (currentWater + size <= burst) {
            // 尝试加水,并且水还未满
            currentWater += size;
            return true;
        } else {
            // 水满，拒绝加水
            return false;
        }
    }


    public static void main(String[] args) throws InterruptedException {
        int capacity = 100;
        double leakingRate = 0.05;
        LeakyBucket leakyBucket = new LeakyBucket(capacity, leakingRate);
        //每100ms()，流入10的水
        //每100ms，流出5的水
        for (int i = 0; i < 100; i++) {
            Boolean isBoolean = leakyBucket.acquire(10);
            System.out.println("本次申请：" + (isBoolean ? "成功" : "失败") +
                    "当前桶内水量：" + leakyBucket.currentWater +
                    " 剩余空间：" + (leakyBucket.burst - leakyBucket.currentWater));
            TimeUnit.MILLISECONDS.sleep(100);
        }
    }
}







